package com.gf.framework.common.utils.hashhash;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * @author gaofei
 * @date 2022/6/12 17:06
 */
public interface IHashHashMap<K1, K2, V>
        extends Iterable<HashHashEntry<K1, K2, V>>, Map<K1, Map<K2, V>> {
    Map<K2, V> createSecondMap();

    default V put(K1 k1, K2 k2, V v) {
        return computeIfAbsent(k1, k-> createSecondMap()).put(k2, v);
    }

    default V putIfAbsent(K1 k1, K2 k2, V v) {
        return computeIfAbsent(k1, k-> createSecondMap()).putIfAbsent(k2, v);
    }

    default V computeIfAbsent(K1 k1, K2 k2, Function<? super K2, ? extends V> mappingFunction) {
        return computeIfAbsent(k1, k-> createSecondMap()).computeIfAbsent(k2, mappingFunction);
    }

    default V computeIfPresent(K1 k1, K2 k2, BiFunction<? super K2, ? super V, ? extends V> remappingFunction) {
        Map<K2, V> map = get(k1);
        if (map == null) {
            return null;
        }

        return map.computeIfPresent(k2, remappingFunction);
    }

    default V get(K1 k1, K2 k2) {
        Map<K2, V> hashMap = get(k1);
        if (hashMap == null) {
            return null;
        }
        return hashMap.get(k2);
    }

    default int valueSize() {
        int size = 0;
        for (Map<K2, V> map : values()) {
            size += map.size();
        }
        return size;
    }

    default List<HashHashEntry<K1, K2, V>> hashHashEntryList() {
        return new HashHashItr<>(valueSize(), entrySet()).getHashHashEntries();
    }

    default Set<HashHashEntry<K1, K2, V>> hashHashEntrySet() {
        return new HashSet<>(hashHashEntryList());
    }

    @Override
    default Iterator<HashHashEntry<K1, K2, V>> iterator() {
        return new HashHashItr<>(valueSize(), entrySet());
    }
}
